# -*- coding: utf-8 -*-
# @Time : 2023/3/14
# @Author : 限量老

from django.db.models.signals import post_save
from django.conf import settings
from django.dispatch import receiver
from rest_framework import status
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import generics
from rest_framework import viewsets
from rest_framework.authtoken.models import Token
from rest_framework.authentication import BasicAuthentication,SessionAuthentication,TokenAuthentication
from rest_framework.permissions import IsAuthenticated

from .models import Course
from .serializers import CourseSerializer
from .permissions import IsOwnerReadOnly

'''
1.使用django manage.py生成Token  ==>  'python manage.py drf_create_token admin'
2.通过django的信号机制生成Token
'''
@receiver(post_save,sender=settings.AUTH_USER_MODEL) #django的信号机制
def generate_token(sender,instance=None,created=False,**kwargs):
    '''
    创建用户时自动生成Token,用户登录时instance=用户,有了instance,就会触发created
    :param sender:
    :param instance:
    :param created:
    :param kwargs:
    :return:
    '''
    if created:
        Token.objects.create(user=instance)


'''一 函数式编程 Function Based View'''


@api_view(['GET', 'POST'])
#三个认证(BasicAuthentication,SessionAuthentication,TokenAuthentication)
#这里部分认证优先于settings.DEFAULT_AUTHENTICATION_CLASSES的全局认证
@authentication_classes((BasicAuthentication,TokenAuthentication))
# @permission_classes((IsAuthenticated,))  #自定义权限
def course_list(request):
    '''
    获取所有课程信息或新增一个课程
    :param request:
    :return:
    '''
    if request.method == 'GET':
        s = CourseSerializer(instance=Course.objects.all(), many=True)  # 序列化多个对象用many=True
        return Response(data=s.data, status=status.HTTP_200_OK)

    elif request.method == 'POST': #新增操作
        s = CourseSerializer(data=request.data)  # 部分更新(非必填的字段)partial=True,
        if s.is_valid():  # 校验成功
            s.save(teacher=request.user)  # teacher在模型类已经设置为只读属性,这里只要把哪个用户post来的就把他设置为teacher
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)  # 如果校验失败

@api_view(["GET","PUT","DELETE"])
#三个认证(BasicAuthentication,SessionAuthentication,TokenAuthentication)
#这里部分认证优先于settings.DEFAULT_AUTHENTICATION_CLASSES的全局认证
@authentication_classes((BasicAuthentication,TokenAuthentication))
# @permission_classes((IsAuthenticated,))  #自定义权限
def course_detail(request,pk):
    '''
    获取,更新,删除一个课程
    :param request:
    :param pk:
    :return:
    '''
    try:
        course=Course.objects.get(pk=pk)
    except Course.DoesNotExist:
        return Response(data={"msg":"没有此课程信息"},status=status.HTTP_404_NOT_FOUND)
    else:
        if request.method=="GET": #单条数据
            s=CourseSerializer(instance=course)
            return Response(data=s.data,status=status.HTTP_200_OK)

        elif request.method=="PUT": #更新操作
            s=CourseSerializer(instance=course,data=request.data)#instance你要序列化哪个实例,data哪里来的
            if s.is_valid():
                s.save() #"PUT": #更新操作不需要 teacher=request.user,  "POST":#新增操作必须传入teacher=request.user
                return Response(s.data,status=status.HTTP_200_OK)

        elif request.method=="DELETE":
            course.delete()
            return Response(status=status.HTTP_404_NOT_FOUND)


'''二 类视图 Class Based View'''

class CourseList(APIView):

    #部份认证:
    # authentication_classes = (BasicAuthentication,SessionAuthentication,TokenAuthentication)
    # permission_classes((IsAuthenticated,))  # 自定义权限

    def get(self,request):

        '''print(self.request.user,self.request.auth)
        admin None'''

        queryset=Course.objects.all()
        s=CourseSerializer(instance=queryset,many=True)  #instance是查询集的数据
        return Response(s.data,status=status.HTTP_200_OK)

    def post(self, request):
        s=CourseSerializer(data=request.data)  #data是前端传过来的数据,return前,要先校验
        if s.is_valid():
            s.save(teacher=self.request.user)

            '''print(type(request.data),type(s.data))   ===>
            <class 'dict'> <class 'rest_framework.utils.serializer_helpers.ReturnDict'>'''

            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)  # 如果校验失败


class CourseDetail(APIView):#处理单一对象

    # 部份认证:
    # authentication_classes = (BasicAuthentication,SessionAuthentication,TokenAuthentication)
    # permission_classes((IsAuthenticated,))  # 自定义权限

    @staticmethod
    def get_object(pk): #用通用的方法获取单一对象
        try:
            return Course.objects.get(pk=pk)
        except Course.DoesNotExist:
            return #不存在返回空值

    def get(self,request,pk):
        obj=self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s=CourseSerializer(instance=obj)
        return Response(s.data,status=status.HTTP_200_OK)

    def put(self,request,pk): #更新全部
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        s = CourseSerializer(instance=obj,data=request.data)
        if s.is_valid():
            s.save()
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)  # 如果校验失败

    # def patch(self,request,pk): #部分更新
    #     obj = self.get_object(pk=pk)
    #     if not obj:
    #         return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
    #     s = CourseSerializer(instance=obj, data=request.data)
    #     if s.is_valid():
    #         s.save()
    #         return Response(data=s.data, status=status.HTTP_201_CREATED)
    #     return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)  # 如果校验失败

    def delete(self,request,pk):
        obj = self.get_object(pk=pk)
        if not obj:
            return Response(data={"msg": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


'''三 通用类视图 Generic Classed Based View'''

class GCourseList(generics.ListCreateAPIView): #查所有|创建业务

    # 部份认证:
    # authentication_classes = (BasicAuthentication,SessionAuthentication,TokenAuthentication)
    # permission_classes((IsAuthenticated,))  # 自定义权限

    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    def perform_create(self, serializer): #重写自定义保存操作:teacher=self.request.user
        serializer.save(teacher=self.request.user)


class GCourseDetail(generics.RetrieveUpdateDestroyAPIView): #查单一|更新一个|删除一个     课程信息的修改
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    permission_classes = (IsAuthenticated,IsOwnerReadOnly)  #自定义写权限限制


'''四 DRF的视图集viewsets'''

class CourseViewSet(viewsets.ModelViewSet):
    # 部份认证:
    # authentication_classes = (BasicAuthentication,SessionAuthentication,TokenAuthentication)

    queryset = Course.objects.all()
    serializer_class = CourseSerializer

    permission_classes = (IsAuthenticated, IsOwnerReadOnly)  # 自定义写权限限制

    def perform_create(self, serializer): #重写自定义保存操作:teacher=self.request.user
        serializer.save(teacher=self.request.user)

